/*
XPTracker - Alternative Agile Tracking Tool
Copyright (C) 2006-2009  Stephen Starkey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package org.xptracker.util;

import java.util.List;

public class SideBySideRenderer<T extends Comparable> {
  private Diff<T> diff;
  private List<Diff.Segment<T>> computedDifferences;

  public SideBySideRenderer(Diff<T> diff) {
    this.diff = diff;
  }

  public void render(Printer<T> printer) throws Exception {
    if (computedDifferences == null) {
      computedDifferences = diff.computeDifferences();
    }

    printer.printHeader();
    for(Diff.Segment<T> difference: computedDifferences) {
      if (difference.isCommon()) {
        for(T item: difference.getCommonLines()) {
          printer.printLine(true, item, item);
        }
      } else {
        T[] leftLines = difference.getLeftLines();
        T[] rightLines = difference.getRightLines();
        int i = 0;
        int j = 0;
        int leftLen = leftLines.length;
        int rightLen = rightLines.length;

        while (i < leftLen || j < rightLen) {
          if (i < leftLen && j < rightLen) {
            printer.printLine(false, leftLines[i], rightLines[j]);
          } else if (i < leftLen) {
            printer.printLine(false, leftLines[i], null);
          } else if (j < rightLen) {
            printer.printLine(false, null, rightLines[j]);
          }

          i++;
          j++;
        }
      }
    }
    printer.printFooter();
  }

  public interface Printer<U> {
    void printHeader() throws Exception;
    void printFooter() throws Exception;
    void printLine(boolean common, U left, U right) throws Exception;
  }
}
